home *** CD-ROM | disk | FTP | other *** search
/ Aminet 34 / Aminet 34 (2000)(Schatztruhe)[!][Dec 1999].iso / Aminet / util / sys / JoinReplace.lha / Source / Join.c next >
Encoding:
C/C++ Source or Header  |  1999-09-08  |  13.7 KB  |  544 lines

  1. #define NAME     "Join"
  2. #define REVISION "19"
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        Join
  7.     Author:        SDI
  8.     Distribution:    PD
  9.     Description:    joins files to one big file
  10.     Compileropts:    -
  11.     Linkeropts:    -gsi
  12.  
  13.  1.4   03.10.95 : JoinToH and JoinToAG included
  14.  1.5   04.10.95 : AS as synonym for TO
  15.  1.6   15.10.95 : recompiled
  16.  1.7   15.02.95 : parameters now like in C:Join! AS=TO/K/A, FILE/M/A and
  17.     new parameter FILELIST --> Same function like before needs now AS
  18.     or TO and FILELIST!, used own startup code, new option NAMEHEADER
  19.  1.8   16.02.96 : option NAMEHEADER now also processes very long file names,
  20.     removed some other bugs
  21.  1.9   17.04.96 : added options ADD and DELSOURCE
  22.  1.10  27.04.96 : fixed error with name-printout, added option QUIET
  23.  1.11  04.05.96 : fixed error with ReadArgs
  24.  1.12  28.05.96 : now uses SDI_defines SDI_ENDCODE
  25.  1.13  12.02.97 : added option SPLITTED
  26.  1.14  18.03.97 : SDI include names changed
  27.  1.15  01.05.97 : added pattern matching, ALL and PATTERN options, made
  28.     multi-reentrant (pure bit) and removed SDI funcs this way
  29.  1.16  03.05.97 : added workbench tooltype call
  30.  1.17  04.05.97 : fixed a little bug
  31.  1.18  07.06.97 : fixed problem, when source == destination
  32.  1.19  21.08.99 : fixed PATTERN Problem
  33. */
  34.  
  35. #include <proto/dos.h>
  36. #include <proto/exec.h>
  37. #include <proto/icon.h>
  38. #include <workbench/startup.h>
  39. #include <exec/memory.h>
  40. #include "SDI_defines.h"
  41. #include "SDI_ASM_STD_protos.h"
  42.  
  43. #define PARAM    "FILE/M,AS=TO/K/A,FILELIST/K,SPLITTED/K,PAT=PATTERN/K," \
  44.         "OUTPUT/K,AG=AMIGAGUIDE/S,HEADER/S,NAMEHEADER/S,ADD/S,"    \
  45.         "DEL=DELSOURCE/S,QUIET/S,ALL/S,NOPAT=NOPATTERN/S"
  46. #define PATHNAME_SIZE    256
  47. #define NAMEHEADER_SIZE    69
  48. #define HEADERLINE_SIZE 78
  49.  
  50. #define JOINFLAG_AMIGAGUIDE    (1<<0)
  51. #define JOINFLAG_HEADER        (1<<1)
  52. #define JOINFLAG_NAMEHEADER    (1<<2)
  53. #define JOINFLAG_DELSOURCE    (1<<3)
  54. #define JOINFLAG_QUIET        (1<<4)
  55. #define JOINFLAG_NOPATTERN    (1<<5)
  56. #define JOINFLAG_ALL        (1<<6)
  57.  
  58. #define JOINERR_NOMEM        1
  59. #define JOINERR_NOFILE        2
  60. #define JOINERR_READERR        3
  61. #define JOINERR_WRITEERR    4
  62. #define JOINERR_BREAK        5
  63.  
  64. struct ExecBase *SysBase;
  65. struct DosLibrary *DOSBase;
  66. struct Library *IconBase;
  67. UBYTE line[] =    "\n/* =============================================="
  68.         "======================= */\n\n";
  69.  
  70. ULONG JoinMain(struct CSource *CSource);
  71. ULONG Join(STRPTR name, ULONG filehandle, ULONG Flags);
  72. ULONG PatJoin(STRPTR name, ULONG filehandle, ULONG Flags, STRPTR pat);
  73. ULONG GetLength(ULONG fh);
  74.  
  75. ULONG start(void)
  76. {
  77.   struct Process *task;
  78.   struct WBStartup *msg = 0;
  79.   ULONG ret = RETURN_FAIL;
  80.   struct DosLibrary *dosbase;
  81.   struct CSource csr = {0,0,0};
  82.  
  83.   SysBase = (*((struct ExecBase **) 4));
  84.   /* test for WB and reply startup-message */
  85.   if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  86.   {
  87.     WaitPort(&task->pr_MsgPort);
  88.     msg = (struct WBStartup *) GetMsg(&task->pr_MsgPort);
  89.   }
  90.  
  91.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  92.   {
  93.     DOSBase = dosbase;
  94.     
  95.     if(!msg) /* CLI call - only one argument string */
  96.       ret = JoinMain(&csr);
  97.     else
  98.     {
  99.       struct Library *iconbase;
  100.  
  101.       if((iconbase = OpenLibrary("icon.library", 37)))
  102.       {
  103.         ULONG i;
  104.         IconBase = iconbase;
  105.  
  106.     ret = RETURN_OK;
  107.         for(i = 0; !ret && i < msg->sm_NumArgs; ++i)
  108.         {
  109.       ULONG lock;
  110.       struct DiskObject *dobj;
  111.  
  112.           lock = CurrentDir(msg->sm_ArgList[i].wa_Lock);
  113.           if((dobj = GetDiskObject(msg->sm_ArgList[i].wa_Name)))
  114.           {
  115.             if(dobj->do_ToolTypes)
  116.             {
  117.               char **str = dobj->do_ToolTypes;
  118.  
  119.               while(!ret && *str)
  120.               {
  121.                   STRPTR buf;
  122.          csr.CS_Length = SDI_strlen(*str)+1; /* add \n */
  123.          if((buf = (STRPTR) AllocMem(csr.CS_Length+1, MEMF_ANY)))
  124.          {
  125.            CopyMem(*str, buf, csr.CS_Length);
  126.            buf[csr.CS_Length] = 0;
  127.            buf[csr.CS_Length-1] = '\n';
  128.           csr.CS_Buffer = buf;
  129.           ret = JoinMain(&csr);
  130.           FreeMem(buf, csr.CS_Length+1);
  131.         }
  132.         else
  133.           ret = RETURN_FAIL;
  134.                 ++str;
  135.               }
  136.             }
  137.             FreeDiskObject(dobj);
  138.           }
  139.           CurrentDir(lock);
  140.         }
  141.         CloseLibrary(iconbase);
  142.       }
  143.     }
  144.     CloseLibrary((struct Library *) dosbase);
  145.   }
  146.  
  147.   if(msg)
  148.   {
  149.     Forbid();
  150.     ReplyMsg((struct Message *) msg);
  151.   }
  152.  
  153.   return ret;
  154. }
  155.  
  156. ULONG JoinMain(struct CSource *CSource)
  157. {
  158.   struct {
  159.     STRPTR    *files;
  160.     STRPTR    to;
  161.     STRPTR    filelist;
  162.     STRPTR    splitted;
  163.     STRPTR    pattern;
  164.     STRPTR    output;
  165.     LONG    amigaguide;
  166.     LONG    header;
  167.     LONG    nameheader;
  168.     LONG    add;
  169.     LONG    delsource;
  170.     LONG    quiet;
  171.     LONG    all;
  172.     LONG    nopattern;
  173.     } args = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  174.   LONG i = 0;
  175.   ULONG Flags = 0, ret = RETURN_FAIL, dest, patbufsize = 0, out = 0, oldout = 0;
  176.   STRPTR pattern = 0;
  177.   struct RDArgs *rda;
  178.  
  179.   if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  180.   {
  181.    rda->RDA_ExtHelp =
  182.    "FILES      files, which should be joined\n"
  183.    "FILELIST   takes the filenames out of a file (every line contains\n"
  184.    "           a complete filename)\n"
  185.    "SPLITTED   allows joining splitted files, data has to look like:\n"
  186.    "           <filename>[,<first number>[,<last number>]], filename has\n"
  187.    "           to hold ONE format string like %ld,%03ld,%lx,%2lx,\n"
  188.    "           numbers have to be decimal\n\n"
  189.    "PATTERN    gives pattern filename must match\n"
  190.    "OUTPUT     specifies output path\n\n"
  191.    "AMIGAGUIDE at the start of every file @node \"filename\" and at the\n"
  192.    "           end @endnode is inserted\n"
  193.    "HEADER     /* ======== ... ========= */ is inserted at filestart\n"
  194.    "NAMEHEADER /* ===... filename ...=== */ is inserted at filestart\n"
  195.    "ADD        adds the files to an existing destination file\n"
  196.    "DELSOURCE  deletes the sourcefiles\n"
  197.    "QUIET      brings no output\n"
  198.    "ALL        scan into directories\n"
  199.    "NOPATTERN  take names as given";
  200.  
  201.    rda->RDA_Source.CS_Buffer = CSource->CS_Buffer;
  202.    rda->RDA_Source.CS_Length = CSource->CS_Length;
  203.  
  204.    if(ReadArgs(PARAM, (LONG *) &args, rda))
  205.    {
  206.     if(args.amigaguide)    Flags |= JOINFLAG_AMIGAGUIDE;
  207.     if(args.header)    Flags |= JOINFLAG_HEADER;
  208.     if(args.nameheader)    Flags |= JOINFLAG_NAMEHEADER;
  209.     if(args.delsource)    Flags |= JOINFLAG_DELSOURCE;
  210.     if(args.quiet)    Flags |= JOINFLAG_QUIET;
  211.     if(args.nopattern)    Flags |= JOINFLAG_NOPATTERN;
  212.     if(args.all)    Flags |= JOINFLAG_ALL;
  213.  
  214.     if(args.output && (out = Open(args.output, MODE_NEWFILE)))
  215.       oldout = SelectOutput(out);
  216.  
  217.     if(args.files)    ++i;
  218.     if(args.filelist)    ++i;    /* test if only one of these three */
  219.     if(args.splitted)    ++i;
  220.     if(i == 1 && (dest = Open(args.to, MODE_READWRITE)))
  221.     {
  222.      if(args.add)
  223.       Seek(dest, 0, OFFSET_END);
  224.      else
  225.       SetFileSize(dest, 0, OFFSET_BEGINNING); /* cut when already exists */
  226.  
  227.      if(args.pattern && *args.pattern)
  228.      {
  229.       patbufsize = (SDI_strlen(args.pattern)<<1) + 1;
  230.       if((pattern = (STRPTR) AllocMem(patbufsize, MEMF_PUBLIC)))
  231.       {
  232.        if(ParsePatternNoCase(args.pattern, pattern, patbufsize) < 0)
  233.        {
  234.     FreeMem(pattern, patbufsize); pattern = 0;
  235.        }
  236.       }
  237.      }
  238.  
  239.      if(args.pattern && !pattern)
  240.      {
  241.       if(!*args.pattern)
  242.        SetIoErr(ERROR_BAD_TEMPLATE);
  243.      }
  244.      else if(args.splitted)
  245.      {
  246.       UBYTE name[PATHNAME_SIZE];
  247.       STRPTR a, b, *e = 0, *f = 0;
  248.       LONG spl_start = 0, spl_end = 0;
  249.  
  250.       ret = RETURN_OK;
  251.       for(a = args.splitted; *a && *a != ','; ++a)
  252.        ;
  253.       if(*a == ',')
  254.       {
  255.        *(a++) = 0;
  256.        for(b = a; *b && *b != ','; ++b)
  257.         ;
  258.       
  259.        if(*b == ',')
  260.        {
  261.         *(b++) = 0;
  262.         spl_end = SDI_strtol(b,f,10);
  263.        }
  264.        spl_start = SDI_strtol(a,e,10);
  265.  
  266.        if(e || f || (spl_end && spl_end < spl_start))
  267.        {
  268.         SetIoErr(ERROR_BAD_NUMBER);
  269.         ret = RETURN_FAIL;
  270.        }
  271.       }
  272.  
  273.       while(!ret && (!spl_end || spl_end >= spl_start))
  274.       {
  275.        SDI_sprintf(name, args.splitted, spl_start++);
  276.        if((i = PatJoin(name, dest, Flags, pattern)))
  277.        {
  278.         if(i != JOINERR_NOFILE)
  279.          ret = RETURN_FAIL;
  280.         else if(!spl_end)
  281.          break;
  282.        }
  283.       }
  284.      }
  285.      else if(args.filelist)
  286.      {
  287.       ULONG fh, bufsize;
  288.       STRPTR buffer, pos, name;
  289.  
  290.       if((fh = Open(args.filelist, MODE_OLDFILE)))
  291.       {
  292.        bufsize = GetLength(fh);
  293.        if((pos = buffer = (STRPTR) AllocMem(bufsize+1, MEMF_ANY)))
  294.        {
  295.         if(Read(fh, buffer, bufsize) == bufsize)
  296.     {
  297.          ret = RETURN_OK;
  298.          while(pos < buffer + bufsize)
  299.          {
  300.           name = pos;
  301.           while(pos < buffer + bufsize && *pos != '\n')
  302.        ++pos;
  303.       *(pos++) = 0;
  304.           if(PatJoin(name, dest, Flags, pattern))
  305.            ret = RETURN_FAIL;
  306.          }
  307.         }
  308.         FreeMem(buffer, bufsize+1);
  309.        }
  310.        Close(fh);
  311.       }
  312.      }
  313.      else
  314.      {
  315.       ret = RETURN_OK;
  316.       while(*args.files)
  317.       {
  318.        if(PatJoin(*(args.files++), dest, Flags, pattern))
  319.        {
  320.          ret = RETURN_FAIL; break;
  321.        }
  322.       }
  323.      }
  324.      if(pattern)
  325.       FreeMem(pattern, patbufsize);
  326.      Close(dest);
  327.     } /* Open dest */
  328.     else if(!i)
  329.      SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  330.     else if(i != 1)
  331.      SetIoErr(ERROR_TOO_MANY_ARGS);
  332.  
  333.     FreeArgs(rda);
  334.    } /* ReadArgs */
  335.    FreeDosObject(DOS_RDARGS, rda);
  336.   }
  337.  
  338.   if(!ret && CTRL_C)
  339.   {
  340.     SetIoErr(ERROR_BREAK);
  341.     ret = RETURN_WARN;
  342.   }
  343.  
  344.   if(ret && !args.quiet)
  345.     PrintFault(IoErr(),0);
  346.  
  347.   if(out)
  348.     Close(SelectOutput(oldout));
  349.  
  350.   return ret;
  351. }
  352.  
  353. /* every list entry of filelist is a memory block which contains pointer
  354.    to next block and behind this the filename string */
  355.  
  356. ULONG PatJoin(STRPTR name, ULONG dest, ULONG Flags, STRPTR pattern)
  357. {
  358.   if(Flags & JOINFLAG_NOPATTERN)
  359.     return Join(name, dest, Flags);
  360.   else
  361.   {
  362.    struct AnchorPath *APath;
  363.    ULONG *filelist = 0, *a, *b, retval;
  364.    ULONG ret = JOINERR_NOMEM;
  365.    LONG i;
  366.  
  367.    if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath)+
  368.    PATHNAME_SIZE, MEMF_PUBLIC|MEMF_CLEAR)))
  369.    {
  370.     APath->ap_BreakBits = SIGBREAKF_CTRL_C;
  371.     APath->ap_Strlen = PATHNAME_SIZE;
  372.  
  373.     for(retval = MatchFirst(name, APath); !retval; retval =MatchNext(APath))
  374.     {
  375.      if(APath->ap_Flags & APF_DIDDIR)
  376.        APath->ap_Flags &= ~APF_DIDDIR;
  377.      else if(APath->ap_Info.fib_DirEntryType > 0)
  378.      {
  379.       if(Flags & JOINFLAG_ALL)
  380.        APath->ap_Flags |= APF_DODIR;
  381.      }
  382.      else if(!pattern || MatchPatternNoCase(pattern, APath->ap_Buf))
  383.      {
  384.       i = SDI_strlen(APath->ap_Buf)+1;
  385.       if(!(a = (ULONG *) AllocVec(i+4, MEMF_ANY)))
  386.        break;
  387.       CopyMem(APath->ap_Buf, a+1, i);
  388.       if(!filelist)
  389.       {
  390.        filelist = a; *a = 0;
  391.       }
  392.       else if(SDI_stricmp((STRPTR) (filelist+1), APath->ap_Buf) >= 0)
  393.       {
  394.        *a = (ULONG) filelist; filelist = a;
  395.       }
  396.       else
  397.       {
  398.        for(b = filelist; *b && (i = SDI_stricmp((STRPTR) (*b+4),
  399.        APath->ap_Buf)) < 0; b = (ULONG *) *b)
  400.         ;
  401.        *a = *b; *b = (ULONG) a;
  402.       }
  403.      }
  404.     }
  405.     MatchEnd(APath);
  406.  
  407.     if(retval == ERROR_NO_MORE_ENTRIES)
  408.     {
  409.      for(a = filelist; a; a = (ULONG *) *a)
  410.      {
  411.       if((ret = Join((STRPTR) (a+1), dest, Flags)))
  412.        break;
  413.      }
  414.     }
  415.  
  416.     while(filelist)
  417.     {
  418.      a = (ULONG *) *filelist;
  419.      FreeVec(filelist);
  420.      filelist = a;
  421.     }
  422.     FreeMem(APath, sizeof(struct AnchorPath)+PATHNAME_SIZE);
  423.    }
  424.    return ret;
  425.   }
  426. }
  427.  
  428. ULONG Join(STRPTR name, ULONG dest, ULONG Flags)
  429. {
  430.   ULONG file, lock_old, lock_new, bufsize, ret = 0;
  431.   LONG i;
  432.   UBYTE namebuffer[NAMEHEADER_SIZE+1];
  433.   ULONG namel;
  434.   STRPTR buffer;
  435.  
  436.   if((lock_new = Lock(name, SHARED_LOCK)))
  437.   {
  438.     if((lock_old = DupLockFromFH(dest)))
  439.     {
  440.       if(SameLock(lock_new, lock_old) == LOCK_SAME)
  441.       {
  442.         if(!(Flags & JOINFLAG_QUIET))
  443.           PutStr("Destination file skipped.\n");
  444.         UnLock(lock_new); lock_new = 0;
  445.       }
  446.       UnLock(lock_old);
  447.     }
  448.   }
  449.   else
  450.     ret = JOINERR_NOFILE;
  451.  
  452.   if(!lock_new)
  453.     return ret;
  454.  
  455.   if((file = OpenFromLock(lock_new)))
  456.   {
  457.     bufsize = GetLength(file);
  458.     if((i = AvailMem(MEMF_LARGEST)) < bufsize)
  459.       bufsize = i;
  460.     if((buffer = (STRPTR) AllocMem(bufsize, MEMF_ANY)))
  461.     {
  462.       if(Flags & JOINFLAG_AMIGAGUIDE)
  463.       {
  464.         Write(dest, "@node \"", 7);
  465.     Write(dest, name, i);
  466.     Write(dest, "\"\n", 2);
  467.       }
  468.       if(Flags & JOINFLAG_HEADER && Seek(dest, 0, OFFSET_CURRENT))
  469.         Write(dest, line, HEADERLINE_SIZE);
  470.       namel = SDI_strlen(name);
  471.       if(namel > NAMEHEADER_SIZE)
  472.       {
  473.         namebuffer[0] = namebuffer[1] = namebuffer[2] = '.';
  474.         CopyMem(name+namel-(NAMEHEADER_SIZE-3), namebuffer+3, NAMEHEADER_SIZE-3+1);
  475.         namel = NAMEHEADER_SIZE;
  476.       }
  477.       else
  478.         CopyMem(name, namebuffer, namel+1);
  479.       if(Flags & JOINFLAG_NAMEHEADER)
  480.       {
  481.         i = (NAMEHEADER_SIZE-namel)>>1;
  482.         Write(dest, line, 3+i);
  483.     Write(dest, " ", 1);
  484.         Write(dest, namebuffer, namel);
  485.         Write(dest, " ", 1);
  486.     i += 5+namel;
  487.         Write(dest, line+i, HEADERLINE_SIZE-i);
  488.       }
  489.       while((i = Read(file, buffer, bufsize)) > 0)
  490.       {
  491.         if(Write(dest, buffer, i) == -1)
  492.         {
  493.           ret = JOINERR_WRITEERR; break;
  494.         }
  495.       }
  496.       if(i == -1)
  497.         ret = JOINERR_READERR;
  498.  
  499.       if(!ret && (Flags & JOINFLAG_AMIGAGUIDE))
  500.         Write(dest, "\n@endnode\n\n", 11);
  501.  
  502.       FreeMem(buffer, bufsize);
  503.     }
  504.     else
  505.       ret = JOINERR_NOMEM;
  506.     Close(file);
  507.   }
  508.   else
  509.   {
  510.     UnLock(lock_new);
  511.     ret = JOINERR_NOFILE;
  512.   }
  513.  
  514.   if(!ret)
  515.   {
  516.     if(Flags & JOINFLAG_DELSOURCE)
  517.       DeleteFile(name);
  518.     if(!(Flags & JOINFLAG_QUIET))
  519.     {
  520.       PutStr(namebuffer); PutStr(" joined");
  521.       if(Flags & JOINFLAG_DELSOURCE)
  522.         PutStr(" and deleted");
  523.       PutStr(".\n");
  524.     }
  525.     if(CTRL_C)
  526.       ret = JOINERR_BREAK;
  527.   }
  528.   return ret;
  529. }
  530.  
  531. ULONG GetLength(ULONG fh)
  532. {
  533.   struct FileInfoBlock *fib;
  534.   ULONG ret = 0xFFFFFFFF;
  535.  
  536.   if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
  537.   {
  538.    if(ExamineFH(fh, fib))
  539.     ret = fib->fib_Size;
  540.    FreeDosObject(DOS_FIB,fib);
  541.   }
  542.   return ret;
  543. }
  544.